home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 038a / basprint.zip / BASPRINT.ASM
Assembly Source File  |  1991-06-19  |  19KB  |  809 lines

  1. COMMENT *
  2.  
  3.                  CLUBware  (tm)
  4.  
  5.       BASPRINT - Enhancement to the Basic Interpreter Print statement
  6.  
  7.            Copyright 1984 Rayhawk Automation N.W. Inc
  8.                   P.O. Box 1427
  9.                   Beaverton, Oregon   97075
  10.                                           *
  11.  
  12. SCRDSEG   SEGMENT
  13.  
  14.       ASSUME  CS:SCRDSEG,DS:NOTHING,ES:NOTHING,SS:STACK
  15.  
  16. ORIG_INT10      LABEL  WORD           ; original int 10
  17.       DW      0
  18.       DW      0
  19. ;______________________________________________________________________________
  20.  
  21. ;   Swap the B4 interrupt used by BASIC to print strings.  Swap must be made
  22. ;    after BASIC has been loaded and initialized its environment.  Swap takes
  23. ;    place when BASIC clears the screen.
  24.  
  25.  
  26. ORIG_INTB4      LABEL  WORD           ; original int b4
  27.       DW      0
  28.       DW      0
  29.  
  30.  
  31. INTSWAP   PROC      FAR
  32.  
  33.       CMP      AX,0600h           ; clear screen request?
  34.       JE      DO_SWAP
  35.       JMP      DWORD PTR ORIG_INT10 ; pass call to BIOS
  36.  
  37. DO_SWAP:
  38.       PUSH      DS
  39.       PUSH      AX
  40.  
  41.       SUB      AX,AX            ; address low memory
  42.       MOV      DS,AX
  43.  
  44.       CLI                   ; disable interrupts for a moment
  45.  
  46. ;   vector for B4 is at 2D0
  47.  
  48. ;   have we already taken over this interrupt once before?
  49.  
  50.       CMP      WORD PTR DS:[02D0h],OFFSET PRINTER
  51.       JE      ALREADY_SAVED
  52.  
  53.  
  54. ;   save the original interrupt vector for use by error message reports
  55.  
  56.       MOV      AX,WORD PTR DS:[02D0h]
  57.       MOV      ORIG_INTB4,AX
  58.       MOV      AX,WORD PTR DS:[02D2h]
  59.       MOV      ORIG_INTB4+2,AX
  60.  
  61. ;   replace the original interrupt vector to allow us to intercept prints
  62.  
  63.       MOV      AX,OFFSET PRINTER
  64.       MOV      WORD PTR DS:[02D0h],AX
  65.       MOV      AX,SEG PRINTER
  66.       MOV      WORD PTR DS:[02D2h],AX
  67.  
  68. ALREADY_SAVED:
  69.  
  70.       STI
  71.  
  72.       POP      AX
  73.       POP      DS
  74.       JMP      DWORD PTR ORIG_INT10 ; pass clear screen to BIOS now
  75.  
  76.  
  77.  
  78. INTSWAP   ENDP
  79.  
  80. ;______________________________________________________________________________
  81.  
  82. COMMENT * PRINTER prints a character string on the screen starting
  83.           at the current cursor position.  After the string is
  84.           written to the screen the cursor position is updated
  85.           to just after the string.
  86.  
  87.       To use this routine, INTSWAP must have swapped the interrupt
  88.           vector for intterupt B4 and redirected it to the PRINTER
  89.           subroutine.
  90.  
  91.       The BASPRINT module will take over the INT 10h and make
  92.           this module permanently resident.  When the screen is cleared
  93.           by BASIC,  INTSWAP will swap INT B4 and point the vector
  94.           to the PRINTER subroutine.
  95.  
  96.       Algorithm:
  97.  
  98.          check context for simple text to screen or possibly something
  99.            more involved that basic should handle
  100.  
  101.           1) store character count and mark the flag for type of i/o
  102.           2) load current page from DS:[0049]
  103.           3) load current position on page from DS:[0056]
  104.           4) load attribute for string from DS:[004E]
  105.           5) move character count to CX for use in loop
  106.           6) load type of crt display from 0000:463
  107.           7) address the screen segment
  108.           8) move string to screen while synchronizing
  109.               with horizontal retrace
  110.           9) update cursor position on screen
  111.          10) update cursor position in database at DS:[0056]
  112.          11) leave registers in manner BASIC expects
  113.  
  114.       On entry
  115.           DS:[SI] points to string to write
  116.           DH      contains count of characters to write
  117.           DS:[CX] also points to string and must be updated on exit
  118.           DS:[0049] contains the page to which we write
  119.           DS:[004E] contains the attribute for the text
  120.           DS:[0056] contains the current screen location and must
  121.                    be updated after print is complete
  122.  
  123.  
  124.                                           *
  125. ;______________________________________________________________________________
  126.  
  127. ;  Local data addressable through CS register
  128.  
  129.  
  130. CHAR_COUNT      LABEL  BYTE
  131.       DB      0
  132.  
  133.  
  134. LINE_START      LABEL  WORD
  135.       DW      0               ;  0
  136.       DW      160               ;  1
  137.       DW      320               ;  2
  138.       DW      480               ;  3
  139.       DW      640               ;  4
  140.       DW      800               ;  5
  141.       DW      960               ;  6
  142.       DW      1120               ;  7
  143.       DW      1280               ;  8
  144.       DW      1440               ;  9
  145.  
  146.       DW      1600               ;  10
  147.       DW      1760               ;  11
  148.       DW      1920               ;  12
  149.       DW      2080               ;  13
  150.       DW      2240               ;  14
  151.       DW      2400               ;  15
  152.       DW      2560               ;  16
  153.       DW      2720               ;  17
  154.       DW      2880               ;  18
  155.       DW      3040               ;  19
  156.       DW      3200               ;  20
  157.       DW      3360               ;  21
  158.       DW      3520               ;  22
  159.       DW      3680               ;  23
  160.       DW      3840               ;  24
  161.  
  162. PAGE_START      LABEL  WORD
  163.       DW      0
  164.       DW      4000
  165.       DW      8000
  166.       DW      12000
  167.  
  168. STARTING_PAGE      LABEL  WORD
  169.       DW      0
  170.  
  171. END_OF_PAGE      LABEL  WORD
  172.       DW      0
  173.  
  174. STARTING_LINE      LABEL  WORD
  175.       DW      0
  176.  
  177. RESIDUAL      LABEL  BYTE
  178.       DB      0
  179.  
  180. ROM_SEGMENT      LABEL  WORD           ; basic segment in ROM
  181.       DW      0F600h
  182.  
  183. LOCAL_FLAG      LABEL  BYTE
  184.           DB   00000000b
  185. JUST_BLANKS      EQU  00000001b       ; basic wants just blanks displayed
  186.  
  187.  
  188. ;______________________________________________________________________________
  189.  
  190. COMMENT *
  191.  
  192.    New service routine for interrupt B4
  193.  
  194.      Calls to routine F600:2BA5 generate B4 interrupts.
  195.      These calls come from several places within the BASIC ROM.
  196.      We service calls from two locations: 26CC - call to display a string
  197.                       148D - call to display blanks
  198.      Calls from anywhere else are serviced by the original basic code.
  199.      The two labels corresponding to the two types of calls we service
  200.      are  STRING_IO
  201.       REPEAT_BLANKS
  202.      The code labeled BASIC_IO passes the interrupt back to the basic code
  203.      for service.
  204.                                           *
  205.  
  206.  
  207. PRINTER   PROC      FAR
  208.  
  209.       PUSH      BP
  210.       MOV      BP,SP            ; address the stack
  211.  
  212.  
  213. ;    check context for simple text to screen or possibly something
  214. ;      more involved that basic should handle
  215.  
  216.       CMP      WORD PTR DS:[04E9h],0
  217.       JNE      BASIC_IO
  218.       CMP      WORD PTR DS:[071Fh],0
  219.       JNE      BASIC_IO
  220.       CMP      BYTE PTR DS:[0758h],0
  221.       JNE      BASIC_IO
  222.       CMP      BYTE PTR DS:[071Bh],0
  223.       JNE      BASIC_IO
  224.       CMP      BYTE PTR DS:[0029h],50h  ; 80 bytes per line?
  225.       JNE      BASIC_IO
  226.       CMP      BYTE PTR DS:[0056h],25   ; on bottom line of screen?
  227.       JE      BASIC_IO           ; if so, let basic handle it
  228.       CMP      WORD PTR [BP+8],26CCh  ; just regular i/o?
  229.       JE      STRING_IO
  230.       CMP      WORD PTR [BP+8],148Dh  ; just repeated blanks?
  231.       JE      REPEAT_BLANKS
  232.  
  233. ;    allow original B4 service routine to perform I/O
  234.  
  235. BASIC_IO:
  236.       POP      BP
  237.       JMP      DWORD PTR ORIG_INTB4 ; pass control to original B4
  238.  
  239.  
  240.  
  241. ; ----------
  242.  
  243.  
  244. ;    repeated blanks sent to screen
  245.  
  246. REPEAT_BLANKS:
  247.  
  248.       PUSH      BX               ; save registers used
  249.       PUSH      DX
  250.       PUSH      DI
  251.       PUSH      ES
  252.       PUSH      CX
  253.  
  254.  
  255. ;      ...      1) store character count and mark the flag for type of i/o
  256.  
  257.       MOV      CHAR_COUNT,CH        ; save character count
  258.       OR      LOCAL_FLAG,JUST_BLANKS
  259.       MOV      RESIDUAL,DH           ; dh should be untouched
  260.       JMP      SETUP_START
  261.  
  262.  
  263. ; ----------
  264.  
  265.  
  266. ;    write the string for basic
  267.  
  268. STRING_IO:
  269.  
  270.       PUSH      BX               ; save registers used,
  271.       PUSH      DX
  272.       PUSH      DI
  273.       PUSH      ES
  274.  
  275.  
  276.  
  277. ;      ...      1) backup to start of string and store character count
  278.  
  279.       DEC      SI               ; backup to start of string
  280.       MOV      CHAR_COUNT,DH        ; save character count
  281.       MOV      LOCAL_FLAG,0           ; clear the flag for string i/o
  282.       MOV      RESIDUAL,1           ; dh to contain 1 on exit
  283.  
  284.  
  285. ;      ...      2) load current page from DS:[0049]
  286.  
  287. SETUP_START:
  288.       MOV      BL,BYTE PTR DS:[0049h]    ; load current page
  289.       SUB      BH,BH
  290.       SHL      BX,1               ; convert to a table offset
  291.       MOV      DI,PAGE_START[BX]    ; load start of page
  292.       MOV      STARTING_PAGE,DI     ; save the page
  293.       MOV      END_OF_PAGE,DI       ; save ending page pointer
  294.       ADD      END_OF_PAGE,3840
  295.  
  296.  
  297.  
  298. ;      ...      3) load current position on page from DS:[0056]
  299.  
  300.       MOV      DX,WORD PTR DS:[0056h]    ; load current position
  301.       DEC      DH               ; basic counts from 1 instead of 0
  302.       DEC      DL               ; basic counts from 1 instead of 0
  303.       MOV      BL,DL            ; load row number
  304.       SHL      BX,1               ; two bytes per table entry
  305.       ADD      DI,LINE_START[BX]    ; add in start of line
  306.       MOV      STARTING_LINE,DI     ; store this for later
  307.  
  308.  
  309.       MOV      DL,DH            ; bring down column number
  310.       SUB      DH,DH
  311.       ADD      DI,DX            ; add in column position
  312.       ADD      DI,DX            ; account for attribute bytes
  313.  
  314.  
  315.  
  316. ;      ...      4) load attribute for string from DS:[004E]
  317.  
  318.       MOV      BH,BYTE PTR DS:[004Eh]  ; load attribute for string
  319.  
  320.  
  321.  
  322. ;      ...      5) move character count to CX for use in loop
  323.  
  324.       SUB      CH,CH            ; clear upper byte
  325.       MOV      CL,CHAR_COUNT        ; load the character count
  326.  
  327.  
  328.  
  329. ;      ...      6) load type of crt display from 0000:463
  330.  
  331.       SUB      AX,AX            ; address system memory
  332.       MOV      ES,AX
  333.  
  334.       MOV      DX,WORD PTR ES:[463h]      ; load address of display adapter
  335.       ADD      DX,6                 ; address crt status port
  336.  
  337.  
  338. ;      ...      7) address the screen segment
  339.  
  340.       MOV      AX,0B000h           ; screen seg for monochrome card
  341.       CMP      DX,03DAh           ; is this a graphic card?
  342.       JNE      MONOCHROME
  343.  
  344.       MOV      AX,0B800h           ; load screen seg for graphic card
  345.  
  346. MONOCHROME:
  347.  
  348.       MOV      ES,AX            ; address the screen buffer
  349.  
  350.  
  351.  
  352. ;      ...      8) move string to screen while synchronizing
  353. ;              with horizontal retrace
  354.  
  355.       TEST      LOCAL_FLAG,JUST_BLANKS
  356.       JZ      DISPLAY_LOOP
  357.  
  358.       MOV      BL,20h           ; load a blank
  359. BLANK_LOOP:
  360.       CALL      DISPLAY_CHAR           ; display a line of blanks for basic
  361.       LOOP      BLANK_LOOP
  362.       JMP      UPDATE_POSITION
  363.  
  364.  
  365. DISPLAY_LOOP:
  366.       LODSB                ; load next character
  367.  
  368.       CMP      AL,20h           ; special character?
  369.       JGE      NOT_SPECIAL
  370.       CALL      SPECIAL
  371.       JZ      ANOTHER_CHAR           ; if flag set, go for another character
  372.  
  373. NOT_SPECIAL:
  374.  
  375.       MOV      BL,AL
  376.  
  377.       CLI
  378. HSYNC_WAIT1:
  379.       IN      AL,DX            ; check for horizontal retrace
  380.       TEST      AL,1
  381.       JNZ      HSYNC_WAIT1           ; wait for retrace
  382. HSYNC_WAIT2:
  383.       IN      AL,DX            ; check for horizontal retrace
  384.       TEST      AL,1
  385.       JZ      HSYNC_WAIT2           ; wait for retrace
  386.  
  387.       MOV      AX,BX
  388.       STOSW                ; store character and attribute
  389.  
  390. ANOTHER_CHAR:
  391.       STI
  392.  
  393.       CMP      DI,END_OF_PAGE
  394.       JL      NOT_SCROLLED
  395.  
  396.       MOV      AL,0Dh           ; force a carriage return
  397.       CALL      SPECIAL
  398.  
  399. NOT_SCROLLED:
  400.  
  401.       LOOP      DISPLAY_LOOP           ; repeat cx times
  402.  
  403.  
  404.  
  405. ;      ...     9) update cursor position on screen
  406.  
  407.  
  408. UPDATE_POSITION:
  409.       MOV      AX,DI
  410.       SUB      AX,STARTING_PAGE
  411.       SHR      AX,1               ; eliminate attribute bytes
  412.       SUB      DX,DX
  413.       MOV      BX,80            ; divide by bytes per line
  414.       DIV      BX               ;   quotient in AL (ROW)
  415.                        ;   remainder in DL (COLUMN)
  416.       MOV      DH,AL
  417.       MOV      BH,BYTE PTR DS:[0049h]    ; load page number
  418.       MOV      AH,2               ; request new position
  419.       INT      10h
  420.  
  421.  
  422. ;      ...      10) update cursor position in database at DS:[0056]
  423.  
  424.       XCHG      DH,DL            ; basic likes this reversed
  425.       INC      DH               ; basic counts from 1 instead of 0
  426.       INC      DL               ; basic counts from 1 instead of 0
  427.       MOV      WORD PTR DS:[0056h],DX
  428.  
  429.  
  430. ;      ...      11) leave registers in manner BASIC expects
  431.  
  432.  
  433.       TEST      LOCAL_FLAG,JUST_BLANKS
  434.       JZ      STRING_DISPLAYED
  435.  
  436.       POP      CX               ; restore original blank count
  437.       MOV      CH,1               ; allow basic to decrement this to 0
  438.       JMP      RESTORE_REGS
  439.  
  440.  
  441. STRING_DISPLAYED:               ; for a string
  442.       MOV      CX,SI            ;  CX must point to last character
  443.       DEC      CX
  444.  
  445.  
  446. RESTORE_REGS:
  447.       POP      ES
  448.       POP      DI
  449.       POP      DX
  450.  
  451.       MOV      DH,RESIDUAL           ; let decrement instr take this to zero
  452.                        ;  inside basic interpreter
  453.       POP      BX
  454.       POP      BP
  455.  
  456.  
  457.       ADD      SP,4               ; throw away offset and code segment
  458.                        ;  from INT B4
  459.       POPF                   ; restore flags from interrupt
  460.  
  461.       POP      AX               ; throw away near call on stack
  462.       PUSH      ROM_SEGMENT           ; and convert to a far call
  463.       PUSH      AX
  464.       MOV      AL,20h           ; leave a character in AL for basic
  465.                        ;  to compare against a CR  (0Dh)
  466.       RET                   ; return to ROM
  467.  
  468.  
  469. PRINTER   ENDP
  470.  
  471. ;______________________________________________________________________________
  472.  
  473. ;  subroutine to handle special control characters
  474.  
  475. SPECIAL   PROC      NEAR
  476.  
  477. ; ----------
  478.  
  479.       CMP      AL,0Ah           ; line feed?
  480.       JE      NEW_LINE
  481.  
  482.  
  483. ; ----------
  484.  
  485.       CMP      AL,0Bh           ; home?
  486.       JNE      NOT_HOME
  487.       MOV      DI,STARTING_PAGE     ; start over at top of screen
  488.       MOV      STARTING_LINE,DI
  489.       SUB      AL,AL
  490.       RET
  491.  
  492. NOT_HOME:
  493.  
  494. ; ----------
  495.  
  496.       CMP      AL,0Ch           ; clear screen?
  497.       JNE      NOT_CLEAR
  498.       MOV      DI,STARTING_PAGE
  499.       MOV      STARTING_LINE,DI
  500.       MOV      AL,0               ; clear whole window
  501.       JMP      SHORT SCROLL_SCREEN
  502.  
  503.  
  504. NOT_CLEAR:
  505.  
  506. ; ----------
  507.  
  508.       CMP      AL,0Dh           ; carriage return?
  509.       JNE      NOT_CR
  510.  
  511. NEW_LINE:
  512.       MOV      DI,STARTING_LINE
  513.       ADD      DI,160
  514.       JMP      SHORT TEST_RIGHT
  515.  
  516. NOT_CR:
  517.  
  518. ; ----------
  519.  
  520.       CMP      AL,1Ch           ; move right?
  521.       JNE      NOT_RIGHT
  522.       ADD      DI,2
  523.       JMP      SHORT TEST_RIGHT
  524.  
  525. NOT_RIGHT:
  526.  
  527. ; ----------
  528.  
  529.       CMP      AL,1Dh           ; move left?
  530.       JNE      NOT_LEFT
  531.       SUB      DI,2
  532.       JMP      SHORT TEST_LEFT
  533.  
  534. NOT_LEFT:
  535.  
  536. ; ----------
  537.  
  538.       CMP      AL,1Eh           ; move up?
  539.       JNE      NOT_UP
  540.  
  541.       SUB      DI,160
  542.       JMP      SHORT TEST_LEFT
  543.  
  544. NOT_UP:
  545.  
  546. ; ----------
  547.  
  548.       CMP      AL,1Fh           ; move down?
  549.       JNE      NOT_DOWN
  550.  
  551.       ADD      DI,160
  552.       JMP      SHORT TEST_RIGHT
  553.  
  554. NOT_DOWN:
  555.       JMP      SHORT TEST_FOR_TAB
  556.  
  557. ; ----------
  558.  
  559. TEST_RIGHT:
  560.       MOV      AX,DI            ; are we past line 24?
  561.       SUB      AX,STARTING_PAGE
  562.       CMP      AX,3840
  563.       JL      VALID_RIGHT
  564.       MOV      DI,STARTING_PAGE     ; back at start of last line
  565.       ADD      DI,3680
  566.       MOV      STARTING_LINE,DI
  567.  
  568.       MOV      AL,1               ; scroll one line
  569.       JMP      SHORT SCROLL_SCREEN
  570.  
  571. VALID_RIGHT:
  572.       SUB      AL,AL
  573.       RET
  574.  
  575. ; ----------
  576.  
  577. SCROLL_SCREEN:
  578.       PUSH      CX
  579.       MOV      CX,0               ; start in upper left corner
  580.       PUSH      DX
  581.       MOV      DX,174Fh           ; end in lower right, one line up
  582.       MOV      AH,6
  583.       PUSHF                ; simulate an INT 10
  584.       CALL      DWORD PTR ORIG_INT10
  585.       POP      DX
  586.       POP      CX
  587.       SUB      AL,AL
  588.       RET
  589.  
  590. ; ----------
  591.  
  592. TEST_LEFT:
  593.       CMP      DI,STARTING_PAGE
  594.       JGE      VALID_LEFT
  595.  
  596.       MOV      DI,STARTING_PAGE
  597.  
  598. VALID_LEFT:
  599.       SUB      AL,AL
  600.       RET
  601.  
  602. ; ----------
  603.  
  604. TEST_FOR_TAB:
  605.  
  606.       CMP      AL,09h           ; tab?
  607.       JNE      NOT_TAB
  608.  
  609.       PUSH      CX
  610.       PUSH      DX
  611.       MOV      AX,DI
  612.       SUB      AX,STARTING_LINE
  613.       SHR      AX,1               ; discount attribute bytes
  614.       SUB      DX,DX
  615.       MOV      CX,8
  616.       DIV      CX
  617.       MOV      CX,8               ; tab positions are every 8 charactes
  618.       SUB      CX,DX            ; subtract off remainder
  619.       MOV      BL,' '               ; write some blanks
  620.       POP      DX
  621. TAB_LOOP:
  622.       CALL      DISPLAY_CHAR
  623.       LOOP      TAB_LOOP
  624.  
  625.       POP      CX
  626.       SUB      AL,AL
  627.       RET
  628.  
  629. NOT_TAB:
  630.  
  631. ; ----------
  632.  
  633.       CMP      AL,08h           ; backspace?
  634.       JNE      NOT_BACKSPACE
  635.  
  636.       CMP      DI,STARTING_LINE
  637.       JE      AT_START
  638.       SUB      DI,2               ; back up a space
  639.  
  640. AT_START:
  641.       MOV      BL,' '               ; write a blank
  642.       CALL      DISPLAY_CHAR
  643.  
  644.       SUB      DI,2               ; back up a space
  645.       SUB      AL,AL
  646.       RET
  647.  
  648. NOT_BACKSPACE:
  649.  
  650. ; ----------
  651.  
  652.       MOV      AH,2
  653.       SUB      AH,1               ; set flag to display the char
  654.       RET
  655.  
  656. SPECIAL   ENDP
  657.  
  658. ;______________________________________________________________________________
  659.  
  660. ;  routine to display a character in BL - used only for special characters
  661. ;     attribute is in BH
  662.  
  663.  
  664. DISPLAY_CHAR      PROC    NEAR
  665.  
  666.       CLI
  667. HSYNC_WAIT3:
  668.       IN      AL,DX            ; check for horizontal retrace
  669.       TEST      AL,1
  670.       JNZ      HSYNC_WAIT3           ; wait for retrace
  671. HSYNC_WAIT4:
  672.       IN      AL,DX            ; check for horizontal retrace
  673.       TEST      AL,1
  674.       JZ      HSYNC_WAIT4           ; wait for retrace
  675.  
  676.       MOV      AX,BX
  677.       STOSW                ; store character and attribute
  678.  
  679.       STI
  680.       RET
  681.  
  682. DISPLAY_CHAR      ENDP
  683.  
  684.  
  685. ;______________________________________________________________________________
  686.  
  687. LASTADDR  LABEL   BYTE
  688.  
  689. COPYRIGHT LABEL   BYTE
  690.       DB      10,13
  691.       DB  '         CLUBware  (tm)',10,13,10,13
  692.       DB  'BASPRINT - Enhancement to the Basic Interpreter Print statement'
  693.       DB      10,13,10,13
  694.       DB  '         Copyright 1984 Rayhawk Automation N.W. Inc',10,13
  695.       DB  '                        P.O. Box 1427',10,13
  696.       DB  '                        Beaverton, Oregon   97075',10,13,'$'
  697.  
  698. ;______________________________________________________________________________
  699.  
  700. BASPRINT  PROC      FAR
  701.  
  702.  
  703.       PUSH      DS               ; Push addr of Program Segment Prefix
  704.       SUB      AX,AX            ; Zero AX
  705.       PUSH      AX               ; Push zero onto stack
  706. ;                     (offset of INT 20 within PSP)
  707.  
  708.  
  709. ;              | - - - - - - - - - - - - - - - - - - - - - - - - -|
  710. ;              |                          |
  711. ;              |        take over the INT 10h         |
  712. ;              |        interrupt if not already done     |
  713. ;              |                          |
  714. ;              | - - - - - - - - - - - - - - - - - - - - - - - - -|
  715.  
  716.       MOV      DS,AX            ; address low memory
  717.       LDS      BX,DWORD PTR DS:[02D0h]  ; load interrupt vector for int B4
  718.  
  719.       MOV      AX,WORD PTR PRINTER
  720.       CMP      AX,WORD PTR DS:[BX]
  721.       JNE      NOT_HERE_YET
  722.       MOV      AX,WORD PTR PRINTER+2
  723.       CMP      AX,WORD PTR DS:[BX+2]
  724.       JNE      NOT_HERE_YET
  725.       MOV      AX,WORD PTR PRINTER+4
  726.       CMP      AX,WORD PTR DS:[BX+4]
  727.       JNE      NOT_HERE_YET
  728.       MOV      AX,WORD PTR PRINTER+6
  729.       CMP      AX,WORD PTR DS:[BX+6]
  730.       JNE      NOT_HERE_YET
  731.  
  732.       JMP      ALREADY_RESIDENT
  733.  
  734. NOT_HERE_YET:
  735.       SUB      AX,AX
  736.       MOV      DS,AX
  737.       MOV      AX,WORD PTR DS:[40h] ; save original int10
  738.       MOV      ORIG_INT10,AX
  739.       MOV      AX,WORD PTR DS:[42h]
  740.       MOV      ORIG_INT10+2,AX
  741.  
  742.       MOV      AX,SEG BASPRINT
  743.       MOV      DS,AX
  744.       MOV      DX,OFFSET INTSWAP    ; Load offset of interrupt service mod
  745.       MOV      AX,2510h           ; Prepare for DOS service call type 25
  746. ;                     to establish service for INT 10
  747.       INT      21h               ; Ask DOS to establish service
  748.  
  749. ;              | - - - - - - - - - - - - - - - - - - - - - - - - -|
  750. ;              |                          |
  751. ;              |        issue copyright message         |
  752. ;              |                          |
  753. ;              | - - - - - - - - - - - - - - - - - - - - - - - - -|
  754.  
  755.       MOV      DX,OFFSET COPYRIGHT
  756.       MOV      AH,9
  757.       INT      21h
  758.  
  759.  
  760. ;              | - - - - - - - - - - - - - - - - - - - - - - - - -|
  761. ;              |                          |
  762. ;              |        modify INT 20 into INT 27 in the     |
  763. ;              |        program segment prefix         |
  764. ;              |                          |
  765. ;              | - - - - - - - - - - - - - - - - - - - - - - - - -|
  766.  
  767.       MOV      BYTE PTR ES:[01],27h ; Change INT 20h to INT 27h
  768.  
  769. ;              | - - - - - - - - - - - - - - - - - - - - - - - - -|
  770. ;              |                          |
  771. ;              |     6) load address of ending tag into DX     |
  772. ;              |                          |
  773. ;              | - - - - - - - - - - - - - - - - - - - - - - - - -|
  774.  
  775.       MOV      AX,SEG LASTADDR
  776.       SUB      AX,SEG BASPRINT
  777.       MOV      CL,4               ; prepare for 4 bit shift
  778.       SHL      AX,CL            ; shift up (convert from seg to abs)
  779.       ADD      AX,OFFSET LASTADDR   ; add address of bottom location
  780.       ADD      AX,0103h           ; Pad offset because DOS measures
  781. ;                      offset relative to Program
  782. ;                      Segment Prefix
  783.       MOV      DX,AX            ; leave where DOS will find it
  784.  
  785. ;              | - - - - - - - - - - - - - - - - - - - - - - - - -|
  786. ;              |                          |
  787. ;              |     7) use RET FAR to return to DOS and     |
  788. ;              |        leave service routine resident     |
  789. ;              |                          |
  790. ;              | - - - - - - - - - - - - - - - - - - - - - - - - -|
  791.  
  792. ALREADY_RESIDENT:
  793.  
  794.       RET
  795.  
  796. BASPRINT  ENDP
  797.  
  798. SCRDSEG   ENDS
  799.  
  800. ;______________________________________________________________________________
  801.  
  802.  
  803. STACK      SEGMENT PARA STACK 'STACK'
  804.       DB      24 DUP('STACK***')
  805. TOPSTACK  DB      0
  806. STACK      ENDS
  807.  
  808.       END      BASPRINT
  809.